﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using Core.Interfaces;
using UnityEngine;

namespace Core.StateSystem
{
    /// <summary>
    /// 状态机系统
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class StateSystem<T> : CancelTokenExtension
    {
        /// <summary>
        /// 状态机
        /// </summary>
        protected StateMachine<T> mState;

        /// <summary>
        /// 状态栈（可用于返回使用）
        /// </summary>
        protected Stack<T> mStateStack;

        /// <summary>
        /// 当状态发生改变
        /// </summary>
        public Action<T> OnStateChanged;

        /// <summary>
        /// 当前状态
        /// </summary>
        public T CurrentState => mState.CurrentState;

        public virtual void OnInit()
        {
            mState = new StateMachine<T>();
            mStateStack = new Stack<T>();

            InitStates();

            KKGL.SysEvent.RegHandler(ELifeCycle.OnUpdate, OnUpdate, CancellationToken.None);
        }

        protected abstract void InitStates();

        private void OnUpdate(ITuple obj)
        {
            mState.OnUpdate();
        }

        // public void OnEnable()
        // {
        //     mState.OnStart();
        // }

        // public void OnDisable()
        // {
        //     mState.OnStop();
        // }

        /// <summary>
        /// 切换状态
        /// </summary>
        /// <param name="state">欲切换的状态</param>
        /// <param name="saveState">是否保存上一个状态</param>
        public void ChangeState(T state, bool saveState = false)
        {
            try
            {
                if (mState.CurrentState.Equals(state))
                {
                    return;
                }

                if (saveState)
                {
                    mStateStack.Push(mState.CurrentState);
                }

                Debug.LogFormat("切换状态：{0} -> {1}", mState.CurrentState, state);
                mState.ChangeState(state);
                OnStateChanged?.Invoke(state);
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
                throw;
            }
        }


        /// <summary>
        /// 返回到上一个保存的状态
        /// </summary>
        /// <returns></returns>
        public bool BackState()
        {
            if (mStateStack.Count == 0)
            {
                return false;
            }

            T lastState = mStateStack.Pop();
            mStateStack.Clear();
            ChangeState(lastState);
            return true;
        }
    }
}